const app = getApp()

function inArray(arr, key, val) {//判断uuid和数组的是否对应
  for (let i = 0; i < arr.length; i++) {
    if (arr[i][key] === val) {
      return i;
    }
  }
  return -1;
}

// ArrayBuffer转16进字符串示例
function ab2hex(buffer) {
  var hexArr = Array.prototype.map.call(
    new Uint8Array(buffer),
    function (bit) {
      return ('00' + bit.toString(2)).slice(-2)
    }
  )
  return hexArr.join('');
}
//加密算法
function tets(str){

  var temp1 = new Array();  
  var temp2 = new Array();  
  var pOut = new Array(); 

  let strArr = []
  let sumtemp;
  str = str.replace(/\s*/g,"")  
  for(let i=0;i<str.length;i++){  //将字符一个一个放进数组
      strArr.push(str.charCodeAt(i))
  }            

  let src = [...strArr]


  let sum = 0;
  for(let i = 0; i < 8; i++)
  {
      sum += src[i]; // 将数组的ascill累加
  }


  for (let index = 0; index < 4; index++)
  {
      for (let i = 0; i < 4; i++)
      {
          temp1[(index << 1) + 0] |= (src[(i << 1) + 0] & (1 << (3 - index))) != 0 ? (1 << i) : 0;  // i=1  i|=2  ->  i=i|2 i=3   
      }
      for (let i = 0; i < 4; i++)
      {
          temp1[(index << 1) + 1] |= (src[(i << 1) + 1] & (1 << (3 - index))) != 0 ? (1 << i) : 0;
      }
  }

  let temp = 132;//632
  for (let i = 0; i < 8; i++)
  {
      if (temp1[i] == 0)
      {
          temp1[i] =  (temp += 67);
      }
  }

  for (let i = 0; i < 4; i++)
  {
      sumtemp = temp1[(i << 1) + 0] + temp1[(i << 1) + 1];
      temp2[(i << 1) + 0] =  (temp1[(i << 1) + 0] + sumtemp);
      temp2[(i << 1) + 1] =  (temp1[(i << 1) + 1] + sumtemp);
  }

  for (let i = 0; i < 8; i++)
  {
      if (temp2[i] == 0)
      {
          temp2[i] =  (temp += 59);
      }
  }
  for (let i = 0; i < 4; i++)
  {
      sumtemp = (i << 1) + 1;
      if (sumtemp > 6)
      {
          sumtemp -= 6;
      }
      temp1[(i << 1) + 0] =  (temp2[(i << 1) + 0] ^ temp2[sumtemp + 0]);
      temp1[(i << 1) + 1] = (temp2[(i << 1) + 1] ^ temp2[sumtemp + 1]);
  }

  for (let i = 0; i < 8; i++)
  {
      temp1[i] =  (temp1[i] +  sum + (temp += 78));
  }
  for (let i = 0; i < 8; i++)
  {
      pOut[i] = temp1[i];
  }

  return pOut;
}
//16转字符
function protocolToString(b,len) {
    // 字节数组 转成16进制字符串
    var hs = "";
    var tmp = "";
    for (let n = 0; n < len; n++) {
        // 整数转成十六进制表示
        
        tmp = (b[n] & 0XFF).toString(16);

        // console.log(tmp);
        if (tmp.length == 1) {
            hs = hs + "0" + tmp;
        } else {
            hs = hs + tmp;
        }
    }
    tmp = null;
    return hs.toUpperCase(); // 转成大写
}
//字符转byte数组
function stringToBytes( str ){  
  let ch, st, re = []; 
  for (let i = 0; i < str.length; i++ ) { 
      ch = str.charCodeAt(i);  // get char  
      st = [];                 // set up "stack"  

  do {  
          st.push( ch & 0xFF );  // push byte to stack  
          ch = ch >> 8;          // shift value down by 1 byte  
      }    

      while ( ch );  
      // add stack contents to result  
      // done because chars have "wrong" endianness  
      re = re.concat( st.reverse() ); 
  }  
  return re 
} 
//arraybuffer转字符串
function arrayBufferToString(arr){
  if(typeof arr === 'string') {  
      return arr;  
  }  
  var dataview=new DataView(arr);
  var ints=new Uint8Array(arr.byteLength);
  for(var i=0;i<ints.length;i++){
    ints[i]=dataview.getUint8(i);
  }
  arr=ints;
  var str = '',  
      _arr = arr;  
  for(var i = 0; i < _arr.length; i++) {  
      var one = _arr[i].toString(2),  
          v = one.match(/^1+?(?=0)/);  
      if(v && one.length == 8) {  
          var bytesLength = v[0].length;  
          var store = _arr[i].toString(2).slice(7 - bytesLength);  
          for(var st = 1; st < bytesLength; st++) {  
              store += _arr[st + i].toString(2).slice(2);  
          }  
          str += String.fromCharCode(parseInt(store, 2));  
          i += bytesLength - 1;  
      } else {  
          str += String.fromCharCode(_arr[i]);  
      }  
  }  
  return str; 
}
//crc验证
function getCrc(data){
  let wCRCin = 0xffff;
  let wCPoly = 0x1021;
  for (let b in data) {
      for (let i = 0; i < 8; i++) {
          let bit = ((data[b] >> (7 - i) & 1) == 1);
          let c15 = ((wCRCin >> 15 & 1) == 1);
          wCRCin <<= 1;
          if (c15 ^ bit)
            wCRCin ^= wCPoly;        
      }
  }
  wCRCin &= 0xffff;
  wCRCin ^= 0x0000;

  console.log(wCRCin);
  let st = wCRCin.toString(16)

  while (st.length < 4){
      st = "0"+st;
  }
  // console.log(st);
  // let  bs = stringToBytes(st.toUpperCase());
  return st.toUpperCase();
}
//特定的字符转16
function strToHex(s){
    var len = s.length;
    var data = new Array(len/2);
    for (var i = 0; i < len; i += 2) {
      data[i / 2] = (digit(s.charAt(i)) << 4) + digit(s.charAt(i+1))
    }
    console.log(data);
    return data;   
}
//参照表
function digit(ch) {
  let map = new Map();
  map.set("0",0);
  map.set("1",1);
  map.set("2",2);
  map.set("3",3);
  map.set("4",4);
  map.set("5",5);
  map.set("6",6);
  map.set("7",7);
  map.set("8",8);
  map.set("9",9);
  map.set("A",10);
  map.set("B",11);
  map.set("C",12);
  map.set("D",13);
  map.set("E",14);
  map.set("F",15);
  return map.get(ch)
}
 

Page({
  data: {
    devices: [],
    connected: false,
    chs: [],
    bluetoothEnabled:false,
    canWrite:false,
    latitude:0,
    longitude:0,
    isLock:false,
    loading:false,
    isWrite:true,
    password:'',
    isAutoLink:true,
    isFirsh:true,
    animateLoading:false,
    userName:''
  },
  openBluetoothAdapter() {//初始化蓝牙模块
    wx.openBluetoothAdapter({
      success: (res) => {
        // console.log('openBluetoothAdapter success', res)
        this.startBluetoothDevicesDiscovery()//搜索蓝牙
      },
      fail: (res) => {
        if (res.errCode === 10001) {
          wx.onBluetoothAdapterStateChange(function (res) {
            // console.log('onBluetoothAdapterStateChange', res)
            if (res.available) {
              this.startBluetoothDevicesDiscovery()
            }
          })
        }
      }
    })
  },
  getBluetoothAdapterState() {//获取蓝牙适配器状态
    wx.getBluetoothAdapterState({
      success: (res) => {
        if (res.discovering) {
          this.onBluetoothDeviceFound()
        } else if (res.available) {
          this.startBluetoothDevicesDiscovery()
        }
      }
    })
  },
  startBluetoothDevicesDiscovery() {//开始搜索附近的蓝牙设备
    if (this._discoveryStarted) {
      return
    }
    this._discoveryStarted = true
    wx.startBluetoothDevicesDiscovery({
      allowDuplicatesKey: true,
      success: (res) => {
        this.onBluetoothDeviceFound()//寻找新设备
      },
    })
  },
  stopBluetoothDevicesDiscovery() {//停止搜寻附近的蓝牙设备
    wx.stopBluetoothDevicesDiscovery()
  },
  onBluetoothDeviceFound() {//监听寻找到新设备的事件
    wx.onBluetoothDeviceFound((res) => {
      // console.log(res.devices);
      res.devices.forEach(device => {
        if (!device.name && !device.localName) {
          return
        }
        if(!this.data.isFirsh){
          if((device.localName.includes('A')) && this.data.autoLink){
            this.autoLink()
          }
        }
        if(device.localName.includes('YBK')){
          const foundDevices = this.data.devices
          const idx = inArray(foundDevices, 'deviceId', device.deviceId)
          const data = {}
          if (idx === -1) {
            data[`devices[${foundDevices.length}]`] = device
            data[`devices[${foundDevices.length}]`].loading = false
          } else {
            data[`devices[${idx}]`] = device
            data[`devices[${idx}]`].loading = false
          }  
          this.setData({name:device.localName})
          this.setData(data)    
        }
      })
    })
  },
  createBLEConnection(e) {//连接低功耗蓝牙设备
    const ds = e.currentTarget.dataset
    const deviceId = ds.deviceId
    // const name = ds.localName || ds.name
    let change = `devices[${ds.index}].loading`

    this.data.devices.forEach((ele,index) => {
      this.setData({[`devices[${index}].loading`]:false})
    })

    this.setData({
      deviceCode:name,
      loading:true,
      [change]:true,
      isAutoLink:true,
      animateLoading:true
    })
    this.queryScope()
    wx.setStorageSync('deviceId', ds.deviceId)
    // wx.setStorageSync('name', ds.name)
    wx.setStorageSync('name', this.data.name)

    wx.createBLEConnection({
      deviceId,
      success: (res) => {
        this.setData({
          connected: true,
          // name,
          deviceId,
          loading:false,
          [change]:false,
        })
        this.getBLEDeviceServices(deviceId)
      },
    })
    this.stopBluetoothDevicesDiscovery()
  },
  closeBLEConnection(e) {//断开与低功耗蓝牙设备的连接
    wx.closeBLEConnection({
      deviceId: this.data.deviceId
    })
    console.log(e.currentTarget.dataset);
    this.setData({
      connected: false,
      chs: [],
      canWrite: false,
      isAutoLink:e.currentTarget.dataset.autolink
    })
  },
  getBLEDeviceServices(deviceId) {//获取蓝牙设备所有服务(
    wx.getBLEDeviceServices({
      deviceId,
      success: (res) => {
        // console.log(res,'res');
        for (let i = 0; i < res.services.length; i++) {
          if (res.services[i].isPrimary) {
            // console.log(deviceId, res.services[i].uuid);
            this.getBLEDeviceCharacteristics(deviceId, res.services[i].uuid)
            return
          }
        }
      },
      fail:(res) =>　{
        console.log(res);
      }
    })
  },
  getBLEDeviceCharacteristics(deviceId, serviceId) {//获取蓝牙设备某个服务中所有特征值
    wx.getBLEDeviceCharacteristics({
      deviceId,
      serviceId,
      success: (res) => {
        // console.log('getBLEDeviceCharacteristics success', res.characteristics)
        for (let i = 0; i < res.characteristics.length; i++) {
          let item = res.characteristics[i]
          if (item.properties.read) {//可读时读取
            wx.readBLECharacteristicValue({
              deviceId,
              serviceId,
              characteristicId: item.uuid,
              success(res){
                // console.log('readBLECharacteristicValue:', res)
              }
            })
          }
          if (item.properties.write) {//可写时写入
            // console.log(item);
            this.setData({
              canWrite: true
            })
            this._deviceId = deviceId
            this._serviceId = serviceId
            this._characteristicId = item.uuid
            wx.setStorageSync('serviceId', serviceId)
            wx.setStorageSync('uuid', item.uuid)
            if(this.data.isWrite){
              this.writeBLECharacteristicValue()
            }
          }
          if (item.properties.notify || item.properties.indicate) {
            wx.notifyBLECharacteristicValueChange({
              deviceId,
              serviceId,
              characteristicId: item.uuid,
              state: true,
            })
          }
        }
      },
      fail(res) {
        console.error('getBLEDeviceCharacteristics', res)
      }
    })
    // 操作之前先监听，保证第一时间获取数据
    let strContact = ''
    wx.onBLECharacteristicValueChange((characteristic) => {
      if(arrayBufferToString(characteristic.value).includes('type')){
        strContact = arrayBufferToString(characteristic.value)
      }else{
        strContact += arrayBufferToString(characteristic.value)
      }
      console.log(strContact,strContact.length);
      this.setData({password:strContact})
      if(strContact.length>20){
        console.log(1);
        this.check()
      }
    })

  },
  writeBLECharacteristicValue() {//向低功耗蓝牙设备特征值中写入二进制数据
    /*能发*/
    let arr = stringToBytes('{"type":"pair1"}')
    let buffer = new ArrayBuffer(arr.length)
    let dataView = new DataView(buffer)
    arr.forEach((ele,index)=>{
      dataView.setUint8(index, ele)
    })
    console.log(arr);
    wx.writeBLECharacteristicValue({
      deviceId: this._deviceId,
      serviceId: this._serviceId,
      characteristicId: this._characteristicId,
      value: buffer,
      success:(res)=>{
        // console.log(res);
      },
      fail(res){
        console.log(res,'fail');
      }
    })
  },
  closeBluetoothAdapter() {//关闭蓝牙模块
    wx.closeBluetoothAdapter()
    this._discoveryStarted = false
  },
  getLocation() {//获取位置信息
    wx.getLocation({
      type: 'wgs84',
      success:(res) => {
        // const latitude = res.latitude
        // const longitude = res.longitude
        // const speed = res.speed
        // const accuracy = res.accuracy
        // console.log(latitude)
        // console.log(longitude)
        this.setData({
            latitude:res.latitude,
            longitude:res.longitude
        })
      }
    })
  },
  queryScope(){//查询是否在范围内
    wx.request({
      url: `http://www.yingliyun.com/v999/sys-marketing/login/findNearbyDeviceCode?longitude=${this.data.latitude}&latitude=${this.data.longitude}&deviceCode=${this.data.deviceCode}`,
      //url: `http://www.yingliyun.com/v999/sys-marketing/login/findNearbyDeviceCode?longitude=11.1&latitude=22.2&deviceCode=110232`,
      success:(res)=>{
        res.data.code === 0 ? this.setData({isLock:true}) : this.setData({isLock:false})
      }
    })
  },
  getSystem(){//获取系统信息
    wx.getSystemInfo({
        success:(res)=>{
          this.setData({
            bluetoothEnabled:res.bluetoothEnabled
          })
          if(!res.bluetoothEnabled){
            wx.showToast({
              title: '请打开蓝牙,重新进入小程序',
              icon:'none'
            }) 
          }
        }  
    })
  },
  autoLink(){//自动连接
    let deviceId = wx.getStorageSync('deviceId') || ''
    let name = wx.getStorageSync('name') || ''
    this.setData({
      deviceCode:name
    })
    if(deviceId){
      this.queryScope()
      wx.createBLEConnection({
        deviceId,
        success: (res) => {
          this.setData({
            connected: true,
            name,
            deviceId,
          })
          this.getBLEDeviceServices(deviceId)
        },
        fail(res){
          console.log(res);
        }
      })
      this.stopBluetoothDevicesDiscovery()
    }
  },
  onBLEConnectionStateChange(){// 该方法回调中可以用于处理连接意外断开等异常情况
    wx.onBLEConnectionStateChange((res) => {
      console.log(`device ${res.deviceId} state has changed, connected: ${res.connected}`,res)
      if(!res.connected){
        this.setData({connected:false})
        this._discoveryStarted =false
        this.setData({isFirsh:false})
        this.startBluetoothDevicesDiscovery()
      }
    })    
  },
  async check(){//校验密码
    // console.log(JSON.parse(this.data.password),JSON.parse(this.data.password).data);
    let bufferArr = tets(JSON.parse(this.data.password).data)
    let a = protocolToString(bufferArr,bufferArr.length)
    let str = `{"type":"pair2","data":"${a}"}`
    let pwd = stringToBytes(str)
    let pwdArr = this.chunk(pwd,20)
    this.subcontract(pwdArr)
    this.setData({animateLoading:false})
  },
  chunk(arr, size) {//切割数组
    var arr1=new Array();
    for (var i = 0; i < Math.ceil(arr.length/size); i++) {
      arr1[i]=new Array();
    }
    var j=0;
    var x=0;
    for (var i = 0; i < arr.length; i++) {
      if(!((i%size==0)&&(i!=0))){
        arr1[j][x]=arr[i];
        x++;
      }else{
        j++;
        x=0;
        arr1[j][x]=arr[i];
        x++;
      }
    }
    return arr1;
  },
  openLock(){//开关锁
    this.setData({animateLoading:true})
    let deviceName = this.data.name.slice(-6)
    let str = `AFA1${deviceName}0032000820100005000009BB`
    let arr = strToHex(str+getCrc(strToHex(str)))
    this.subcontract(this.chunk(arr,20))
    let tips = ''
    wx.onBLECharacteristicValueChange(res=>{
      tips += arrayBufferToString(res.value)
      this.setData({animateLoading:false})
      if(tips.length>20 && tips.includes('success')){
        wx.showToast({
          title: '开锁成功！',
          icon:'success'
        }) 
      }else{
        wx.showToast({
          title: '开锁失败！',
          icon:'warn'
        })   
      }
    })
  },
  log(){//上传日志
    let formData = {
      organ_id: userInfo.organId,
      operate_user: userInfo.userName,
      operate_type: '7',   // 	操作类型（1.补货2.开关机3.立即重启4.制冷控制5.定时开关机6.自动重启7.开关锁）String
      operate_terminal: '2',
      device_code: '',
      operate_data: '',
    }
    wx.request({
      url: 'http://www.yingliyun.com/v999/sys-customer/userUpdateLogController/saveUserUpdateLog',
      data:formData
    })
  },
  getOpenID(){//获取openid
    let config = {

    }
  },
  subcontract(arr) {//分包写入
    let buffer,dataView
    let deviceId=wx.getStorageSync('deviceId')
    let serviceId=wx.getStorageSync('serviceId')
    arr.forEach((ele,index)=>{//因为只能传20字节,所以需要分包传输
        if(Array.isArray(ele)){
          buffer = new ArrayBuffer(ele.length)
          dataView = new DataView(buffer)
          ele.forEach((item,idx)=>{
            dataView.setUint8(idx,item)
          })
        }else{
          buffer = new ArrayBuffer(arr.length)
          dataView = new DataView(buffer)
          dataView.setUint8(index,ele)
        }
        // 写入
        wx.writeBLECharacteristicValue({
          deviceId,
          serviceId,
          characteristicId: wx.getStorageSync('uuid'),  
          value: buffer,
        }) 
   
    })
  },
  onLoad:async function () {
    // let a  = app.getCurrentPages()
    // console.log(a);
    await this.getSystem()
    await this.getLocation()
    this.setData({userName:wx.getStorageSync('userName')})
    if(this.data.bluetoothEnabled){
      await this.openBluetoothAdapter()
      this.onBLEConnectionStateChange()
      // setTimeout(function(){
      //   wx.stopBluetoothDevicesDiscovery()
      // }, 6000);
    }
    
  },
  onUnload: function () {
    wx.stopBluetoothDevicesDiscovery()
    this.closeBLEConnection()
    this.closeBluetoothAdapter()
  },
})


